use std::{fmt::Display, path::PathBuf};

use clap::Args;
use serde::{Deserialize, Serialize};

use wtask_base::error::WResult;

use crate::{file::utils::PathNode, utils::AppTrait};


#[derive(Debug, Deserialize, Serialize)]
pub struct FileTree {
    pub root: PathBuf,
    pub deep: u8,
    pub hidden: Option<String>,
    pub tree: PathNode,
}


impl Display for FileTree {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let nodes = self.tree.children_to_string("").join("\n");
        let hidden = if let Some(hidden) = &self.hidden {
            format!(", Hidden: {hidden}")
        } else {
            "".to_owned()
        };
        write!(f, "Root: {}, MaxDeep: {}{}\nis_dir\tname\n{}", self.root.to_str().unwrap(), self.deep, hidden, nodes)
    }
}


#[derive(Debug, Clone, Serialize, Deserialize, Args)]
pub struct AppFileTree {
    /// 文件夹路径
    pub dir: PathBuf,

    /// 隐藏文件前缀
    #[arg(long)]
    pub hidden: Option<String>,

    /// 遍历文件树的深度
    #[arg(long, default_value = "1")]
    pub deep: u8,
}

impl AppTrait for AppFileTree {
    type Status = ();
    type Res = FileTree;

    async fn server_handle_single(self) -> WResult<FileTree> {
        let tree = PathNode::new(&self.dir, self.deep, self.hidden.as_deref());
        Ok(FileTree {
            root: self.dir,
            deep: self.deep,
            hidden: self.hidden,
            tree,
        })
    }
}
